package cc.liyinghao.springsecuritydemo.security.config;


import cc.liyinghao.springsecuritydemo.security.component.RestAuthenticationEntryPoint;
import cc.liyinghao.springsecuritydemo.security.component.RestfulAccessDeniedHandler;
import cc.liyinghao.springsecuritydemo.security.filter.JwtAuthenticationTokenFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;


/**
 * SpringSecurity相关配置
 */
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

    private final IgnoreUrlsConfig ignoreUrlsConfig;
    private final RestfulAccessDeniedHandler restfulAccessDeniedHandler;
    private final RestAuthenticationEntryPoint restAuthenticationEntryPoint;
    private final JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {

        httpSecurity.authorizeRequests()
                .antMatchers(ignoreUrlsConfig.getUrls().toArray(new String[0])).permitAll() // 允许白名单
                .anyRequest().authenticated();  // 其他所有请求需要登录

        httpSecurity.cors().and().csrf().disable();// 允许所有 OPTIONS 请求 否则拿不到请求头

        // 禁用csrf 和 session
        httpSecurity.csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(configurer ->
                        configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

        //jwt token过滤器
        httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        // 添加自定义未授权和未登录结果返回
        httpSecurity.exceptionHandling(customizer ->
                customizer
                        // 处理未授权
                        .accessDeniedHandler(restfulAccessDeniedHandler)
                        // 处理未登录
                        .authenticationEntryPoint(restAuthenticationEntryPoint));
        return httpSecurity.build();
    }
}
